//
//  pj_thuncks_alloc.h
//  pj-lib
//
//  Created by Pang Jun on 2/24/13.
//  Copyright (c) 2013 Pang Jun. All rights reserved.
//

#ifndef pj_lib_pj_thuncks_alloc_h
#define pj_lib_pj_thuncks_alloc_h

#include <stdlib.h>

extern void (* malloc_alloc_oom_handler)() = 0;

class ChunksAlloc
{
private:
    static void* oom_malloc(long size);
    static void* oom_realloc(void* ptr, long size);
    static void (* malloc_alloc_oom_handler)();
public:
    static void* allocate(long size)
    {
        void* chunkPoint = malloc(size);
        if(0 == chunkPoint)
        {
            chunkPoint = oom_malloc(size);
        }
        return chunkPoint;
    }
    
    static void deallocate(void *ptr, long size)
    {
        free(ptr);
    }
    
    static void* reallocate(void *ptr, long old_size, long new_size)
    {
        void * chunkPoint = realloc(ptr, new_size);
        if(0 == chunkPoint)
        {
            chunkPoint = oom_realloc(ptr, new_size);
        }
        return chunkPoint;
    }
    
    static void (* set_malloc_handler(void (*func) ()))()
    {
        void (* old)() = malloc_alloc_oom_handler;
        malloc_alloc_oom_handler = func;
        return(old);
    }
};



void (* ChunksAlloc::malloc_alloc_oom_handler)() = 0;

void * ChunksAlloc::oom_malloc(long n)
{
    void (* my_malloc_handler)();
    void *result;
    for (; ;)
    {
        my_malloc_handler = malloc_alloc_oom_handler;
        if (0 == my_malloc_handler)
        {
            exit(1);
        }
        (*my_malloc_handler)();
        result = malloc(n);
        if (result)
        {
            return (result);
        }
    }
}

void *ChunksAlloc::oom_realloc(void *ptr, long n)
{
    void (* my_malloc_handler)();
    void *result;
    for (; ;)
    {
        my_malloc_handler = malloc_alloc_oom_handler;
        if (0 == my_malloc_handler)
        {
            exit(1);
        }
        (*my_malloc_handler)();
        result = realloc(ptr, n);
        if (result)
        {
            return (result);
        }
    }
    
}


#endif
